perm filename DISPLY.FAI[S,NET] blob
sn#874540 filedate 1989-06-15 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00026 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00005 00002 SUBTTL Display routines, intended to be .INSERTed history NLINES DMLINL DDLINL LINEL DMBUFL NCHARS NWRDLN SCRSIZ NGW DISLIN DMLIN DDDLIN TRUNCA NOEEOL NOEEOB
C00010 00003 Data area DPCBEG DDP IIIP DMP HSIZE VSIZE OVPOS WRAPPD SLUPDP SCUPDP SAUPDP CRUPDP SCRLCT DMCNT DMPNT DPCEND
C00012 00004 Display commands and programs IIIHDR SDISP SCP DP2BEG SCREEN SCREND SCPL BOTLIN VPOS HPOS ROLLP INSDLP CRP LSTATE SCREE1 SCREE2 DP2END FREELF CDISP SCC SCCL LDISP LNP DMDISP DMPGM
C00015 00005 DPYINI -- Initialize display package DPYINI NOTIII
C00017 00006 CLRSCN -- Clear display screen (does explicit update as well) CLRSCN SCRIN1 DMCEOF
C00019 00007 SCSTOR -- Store a character at the current screen V/H position SCSTOR SCSTO2 SCBYTP
C00021 00008 CLREOL -- Clear to end of line CLREOL CLEOL0 CLEOL1
C00023 00009 CLREOF -- Clear to end of screen CLREOF CLEOF1
C00024 00010 CLR1CH -- Delete a character at the cursor CLR1CH CLR1C0
C00025 00011 CSRPOS -- position cursor CSRPOS ADHPOS ADHPO2
C00027 00012 TERPRI -- CR, LF, CLEOL, scroll if necessary TERPRI
C00028 00013 CARRET -- CR CARRET
C00029 00014 LINEFD -- LF, CLEOL, scroll if necessary LINEFD LINFD1 LINFD2
C00031 00015 LINSRV -- Line starve LINSRV LINSR1
C00032 00016 CSRTAB -- Tab cursor CSRTAB CSRTA0
C00033 00017 CSRAOS -- Forespace cursor CSRAOS CSRAO0
C00034 00018 CSRSOS -- Backspace cursor CSRSOS CSRSO0
C00035 00019 INSLIN -- Insert a blank line INSLIN INSLN0 INSL1A INSLN1 INSLN2
C00037 00020 DELLIN -- Delete a blank line DELLIN DELLN0 DELL1A DELLN1
C00039 00021 INSCHR -- Insert a blank character INSCHR INSCH0 INSC1A INSCH2 INSCH1
C00042 00022 DELCHR -- Delete a character DELCHR DELCH0 DELC1A DELCH2 DELCH1
C00045 00023 SCNUPD -- Update screen SCNUPD CSRUPD CSRNOE SCUPD1 SCUP1A SCUPD2 CSRER0 CSRERS
C00050 00024 Save and restore whole screen SCSAV1 SCSAV2 SCSAV3 SCSA12 SCSA21 SCRES1 SCRES2
C00052 00025 GETCSY UPDLIN Redisplay subroutines GETCSY UPDLIN
C00054 00026 DMCHAR DMOUT Datamedia output routines DMCHAR DMOUT
C00056 ENDMK
C⊗;
SUBTTL Display routines, intended to be .INSERTed ;⊗ history NLINES DMLINL DDLINL LINEL DMBUFL NCHARS NWRDLN SCRSIZ NGW DISLIN DMLIN DDDLIN TRUNCA NOEEOL NOEEOB
;This is a library of display hacking routines. Each routine documents its
;calling sequence and what AC's it smashes. Only AC's 0-6 are used. A
;pushdown stack is expected in 17.
;Original implementation by Mark Crispin, SU-AI, July 1978
COMMENT ⊗ History (please record changes):
26 Feb 84 JJW Conversion from MIDAS to FAIL.
28 May 86 ME Put in tests for HPOS overflowing buffers, to avoid clobbering
things outside SCREEN array with characters. Also, SCSTOR
fixed to wrap around automatically (with CR and LF) if attempt
to store character beyond right margin (HSIZE).
11 Sep 87 JJW Changed CAMGE 2,HSIZE to CAMG at SCSTOR+1 since HSIZE is one
less than the number of columns.
03 Dec 88 ME Improved CSRUPD routine, simultaneously allowing wider cursor.
Display tiny cursor at beginning of line that cursor is on.
Added one to NGW to avoid clobbering DD execute at end of SCC.
10 Dec 88 ME Fixed wrapping around to set cursor position to next line
immediately so that display commands from there won't be
ignored for being beyond the end of the previous line.
11 Dec 88 ME Flushed silly SOS'ing of HSIZE -- store true horiz width.
Fixed various comparisons against HSIZE.
27 Jan 89 ME Added routines to save and restore the screen state
(text, cursor position, roll mode, i/d, CR mode), with
two separate copies. See SCSAV1.
history: end of comment ⊗
BEGIN DISPLY
; Useful definitions
NLINES←←=40 ; lines in screen matrix
LINEL←←=88 ; true maximum number of characters/line
DMBUFL←←=100 ; size of DM buffer
NCHARS←←<<<LINEL+5>/5>*5> ; characters/line in line array
NWRDLN←←4+NCHARS/5 ; number of words in line array
SCRSIZ←←NLINES*NWRDLN ; number of words in screen matrix
NGW←←1+<<<NCHARS*3>+=17>/=16> ; number of graphics words
; Line characteristics bits
DISLIN←←<400000,,0> ; III
DMLIN←← <040000,,0> ; DM
DDDLIN←←<020000,,0> ; DD
; DM UPGIOT flags
TRUNCA←←<040000,,0> ; truncate output lines to =80 characters
NOEEOL←←<020000,,0> ; suppress CEOL when moving to a line
NOEEOB←←<010000,,0> ; suppress CEOL on blank line
; Generate a Data Disc/III command
DEFINE DDCMD(O1,D1,O2,D2,O3,D3)<
BYTE (8)D1,D2,D3(3)O1,O2,O3,4
>;DEFINE
; Insert a command in a DM display program
DEFINE DMCMD(CH)<
MOVE DMCNT
CAIGE 10
PUSHJ 17,DMOUT
MOVEI 177
PUSHJ 17,DMCHAR
MOVEI CH
PUSHJ 17,DMCHAR
>;DEFINE
; Data area ;⊗ DPCBEG DDP IIIP DMP HSIZE VSIZE OVPOS WRAPPD SLUPDP SCUPDP SAUPDP CRUPDP SCRLCT DMCNT DMPNT DPCEND
↑DPCBEG←←. ; beginning of core area zeroed at DPYINI
; Terminal characteristics
DDP: BLOCK 1 ; -1 → Data Disc
IIIP: BLOCK 1 ; -1 → III
DMP: BLOCK 1 ; -1 → Datamedia
↑HSIZE: BLOCK 1 ; horizontal size
↑VSIZE: BLOCK 1 ; vertical size
; Cursor position pointers
OVPOS: BLOCK 1 ; old vertical position
WRAPPD: BLOCK 1 ; -1 if just wrapped around, 0,,-1 after CR
; Screen updating flags
SLUPDP: BLOCK NLINES ; -1 → this line has changed
SCUPDP: BLOCK 1 ; -1 → some update happened someplace
SAUPDP: BLOCK 1 ; -1 → updated whole screen
CRUPDP: BLOCK 1 ; -1 → updated cursor
SCRLCT: BLOCK 1 ; for forcing update in LINEFD scrolling
; DM display fields
DMCNT: BLOCK 1 ; DM program counter
DMPNT: BLOCK 1 ; DM program counter
DPCEND←←.-1 ; end of core data
; Display commands and programs ;⊗ IIIHDR SDISP SCP DP2BEG SCREEN SCREND SCPL BOTLIN VPOS HPOS ROLLP INSDLP CRP LSTATE SCREE1 SCREE2 DP2END FREELF CDISP SCC SCCL LDISP LNP DMDISP DMPGM
IIIHDR: BYTE (11)<-777>,640(3)4,2(2)1,2(4)6
SDISP: 600000,,SCP ↔ SCPL ↔ 0 ↔ SCP ; display screen
SCP: DDCMD 1,46,4,1,5,10
DDCMD 3,2,3,2,3,2
DP2BEG←←. ; another area cleared at DPYINI
SCREEN: BLOCK SCRSIZ
SCREND←.-1
0
SCPL←←.-SCP
BOTLIN←←SCREEN+SCRSIZ-NWRDLN+2-1
↑VPOS: BLOCK 1 ; vertical position
↑HPOS: BLOCK 1 ; horizontal position
↑ROLLP: BLOCK 1 ; -1 → scrolling permission
↑INSDLP:BLOCK 1 ;-1 → insert/delete mode on
↑CRP: BLOCK 1 ;-1 → last character CR, ignore LF
LSTATE←←.-SCREEN ; length of array describing screen state
SCREE1: BLOCK LSTATE ; first saved state of screen
SCREE2: BLOCK LSTATE ; second saved state of screen
DP2END←←.-1 ; end of area cleared at DPYINI
↑FREELF:BLOCK 1 ;-1 → invent LF after CR, ignore real LF there
CDISP: SCC ↔ SCCL ↔ 0 ↔ SCC+1 ; display cursor
SCC: DDCMD 1,7,1,7,1,7
DDCMD 3,1,4,0,5,0
BLOCK NGW
DDCMD 0,0,1,46,1,46
0
SCCL←←.-SCC
LDISP: 200000,,LNP ↔ NWRDLN ↔ 0 ↔ LNP ; display line
LNP: DDCMD 1,46,4,0,5,0
DDCMD 3,2,3,2,3,2
BLOCK NWRDLN-3
0
DMDISP: TRUNCA!NOEEOL!NOEEOB+DMPGM ↔ 0 ↔ 0; DM display program
DMPGM: BLOCK DMBUFL
; DPYINI -- Initialize display package ;⊗ DPYINI NOTIII
; Call: PUSHJ 17,DPYINI
; <return>
; Smashes 0.
↑DPYRDW:SETOM SAUPDP ;force text to be redrawn
SETOM CRUPDP ;force cursor to be redrawn
PPACT
LEYPOS 2000 ; flush page printer and line editor
POPJ 17,
↑DPYINI:SETZM DPCBEG
MOVE [DPCBEG,,DPCBEG+1]
BLT DPCEND ; initialize data area
SETZM DP2BEG
MOVE [DP2BEG,,DP2BEG+1]
BLT DP2END ; initialize display area
SETOM FREELF ; insert LF after CR
HRROI [3000,,] ; real line chars
TTYSET ; get my line characteristics
TLNN (DISLIN!DDDLIN!DMLIN) ; display
JRST [ OUTSTR [ASCIZ/Not a display!/]
EXIT]
TLNE (DISLIN)
SETOM IIIP
TLNE (DDDLIN)
SETOM DDP
TLNE (DMLIN)
SETOM DMP
MOVE [-2,,[6000,,HSIZE ↔ 15000,,VSIZE]]
TTYSET ; get screen size information
MOVNI 2 ↔ ADDM VSIZE
;; SOS HSIZE
PPACT
LEYPOS 2000 ; flush page printer and line editor
MOVE VSIZE
MOVEM SCRLCT
SETOM ROLLP ; grant scrolling permission
SKIPN IIIP
JRST NOTIII
SETZM SCP ; different header for III's
MOVE IIIHDR
MOVEM SCP+1
NOTIII: SETOM OVPOS
SKIPN DMP
POPJ 17,
MOVEI <5*DMBUFL>-4
MOVEM DMCNT ; initialize DM counter
MOVE [440700,,DMPGM]
MOVEM DMPNT ; initialize DM pointer
POPJ 17,
; CLRSCN -- Clear display screen (does explicit update as well) ;⊗ CLRSCN SCRIN1 DMCEOF
; Call: PUSHJ 17,CLRSCN
; <return>
; Smashes 0, 1, 2, and 3.
↑CLRSCN:SETZM VPOS
SETZM HPOS
SETZM WRAPPD ; haven't wrapped around
MOVE [<ASCII/ />+1]
MOVEM SCREEN
MOVE [SCREEN,,SCREEN+1]
BLT SCREND ; initialize screen to spaces
MOVE [<ASCII/
/>+1] ; terpri
SETZ 1, ; line address
DMOVE 2,[1 ↔ NLINES] ; blank word/line counter
SCRIN1: MOVEM 2,SCREEN(1)
MOVEM 2,SCREEN+1(1)
MOVEM SCREEN+NWRDLN-2(1)
MOVEM 2,SCREEN+NWRDLN-1(1)
ADDI 1,NWRDLN
SETZM SLUPDP-1(3) ; clear update necessary state for line
SOJG 3,SCRIN1
MOVEI 2
MOVEM SCC+2
MOVE [SCC+2,,SCC+3]
BLT SCC+2+NGW-1 ; initialize graphics words
SETOM SAUPDP ; updated entire screen
PUSHJ 17,SCNUPD
SKIPN DMP
POPJ 17,
DMCMD 14 ; cursor ← [0,2]
MOVEI 140
PUSHJ 17,DMCHAR
MOVEI 142
PUSHJ 17,DMCHAR
MOVE 1,VSIZE
DMCEOF: DMCMD 27 ; clear current line
DMCMD 15 ; move to next line
SOJG 1,DMCEOF
DMCMD 14 ; cursor ← [0,2]
MOVEI 140
PUSHJ 17,DMCHAR
MOVEI 142
PUSHJ 17,DMCHAR
JRST DMOUT
; SCSTOR -- Store a character at the current screen V/H position ;⊗ SCSTOR SCSTO2 SCBYTP
; Call: MOVE <character>
; PUSHJ 17,SCSTOR
; <return>
; Smashes 0, 1, 2, and 3.
↑SCSTOR:MOVE 2,HPOS
CAMGE 2,HSIZE ; this should no longer ever skip
JRST SCSTO2
PUSH 17,0 ; save char to be stored
PUSHJ 17,CARRET ; wrap around with CR
PUSHJ 17,LINEFD ; and LF
POP 17,0
MOVE 2,HPOS ; get new position
SCSTO2: MOVE 1,VPOS
SETOM SLUPDP(1) ; updated flags
SETOM SCUPDP
IMULI 1,NWRDLN
IDIVI 2,5 ; word position in line
ADDI 1,SCREEN+2(2) ; offset by lines previous
DPB 0,SCBYTP(3) ; save character on screen
PUSHJ 17,ADHPOS ; advance HPOS and check for wrap around
SKIPE DMP
JRST DMCHAR
POPJ 17,
; Byte pointer table for insertions
SCBYTP: 350700,,(1)
260700,,(1)
170700,,(1)
100700,,(1)
010700,,(1)
; CLREOL -- Clear to end of line ;⊗ CLREOL CLEOL0 CLEOL1
; Call: PUSHJ 17,CLREOL
; <return>
; Smashes 0, 1, 2, 3, and 4.
; (On DM3025, this doesn't clear "wrapped-around", so we don't clear it here.)
↑CLREOL:SKIPN DMP
JRST CLEOL0
DMCMD 27 ; clear to end of line
CLEOL0: MOVE 4,HPOS
CAIL 4,LINEL
POPJ 17,
MOVE 1,VPOS
SETOM SLUPDP(1) ; flag this line changed
SETOM SCUPDP
IMULI 1,NWRDLN
MOVE 2,HPOS
IDIVI 2,5
ADDI 1,SCREEN+2(2) ; address of word to hack
MOVE 2,SCBYTP(3)
MOVEI " "
DPB 2 ; clear character
CLEOL1: ADDI 4,1 ; next character position
CAIL 4,LINEL
POPJ 17,
IDPB 2
JRST CLEOL1
; CLREOF -- Clear to end of screen ;⊗ CLREOF CLEOF1
; Call: PUSHJ 17,CLREOF
; <return>
; Smashes 0, 1, 2, 3, and 4.
↑CLREOF:PUSH 17,HPOS
PUSH 17,VPOS
CLEOF1: PUSHJ 17,CLREOL ; clear to end of line
DMCMD 15 ; next line
SETZM HPOS
AOS 1,VPOS
CAIGE 1,NLINES
JRST CLEOF1
POP 17,VPOS
POP 17,HPOS
DMCMD 14 ; cursor ← [0,2]
MOVEI 140
PUSHJ 17,DMCHAR
MOVEI 142
PUSHJ 17,DMCHAR
POPJ 17,
; CLR1CH -- Delete a character at the cursor ;⊗ CLR1CH CLR1C0
; Call: PUSHJ 17,CLR1CH
; <return>
; Smashes 0, 1, 2, and 3.
↑CLR1CH:SKIPN DMP
JRST CLR1C0
DMCMD " " ; space then backspace
DMCMD 10
CLR1C0: MOVEI " " ; store space at cursor
MOVE 1,VPOS
SETOM SLUPDP(1)
SETOM SCUPDP
IMULI 1,NWRDLN
SETZM WRAPPD ; forget about any previous wrap around
MOVE 2,HPOS
CAIL 2,LINEL ; within valid range?
POPJ 17, ; no
IDIVI 2,5
ADDI 1,SCREEN+2(2)
DPB SCBYTP(3)
POPJ 17,
; CSRPOS -- position cursor ;⊗ CSRPOS ADHPOS ADHPO2
; Call: MOVE [xpos,,ypos]
; PUSHJ 17,CSRPOS
; <return>
; Smashes 0.
↑CSRPOS:HLRZM HPOS
HRRZM VPOS
HLRZ 0,0 ;just the horizontal position
CAML 0,HSIZE ;off right edge of screen?
SETZM HPOS ;yes, (some) real DMs go to col 0 in this case
SETZM WRAPPD ;forget about any previous wrap around
SETOM CRUPDP
SKIPN DMP
POPJ 17,
DMCMD 14
MOVE HPOS
XORI 140
PUSHJ 17,DMCHAR
MOVE VPOS
ADDI 2
XORI 140
JRST DMCHAR
;Advance cursor position by one, check for wrap around.
;Smashes only AC 0.
ADHPOS: AOS HPOS ;advance cursor position
MOVE 0,HPOS ;get new value
ADHPO2: SETZM WRAPPD ;assume haven't wrapped around now
CAMGE 0,HSIZE ;off edge of screen
POPJ 17, ;no
PUSHJ 17,CARRET ;wrap around with CR
PUSH 17,1
PUSH 17,2
PUSH 17,3
PUSH 17,4
PUSHJ 17,LINEFD ;and LF
POP 17,4
POP 17,3
POP 17,2
POP 17,1
SETOM WRAPPD ;remember we wrapped around
POPJ 17,
; TERPRI -- CR, LF, CLEOL, scroll if necessary ;⊗ TERPRI
; Call: PUSHJ 17,TERPRI
; <return>
; Smashes 0, 1, 2, 3, and 4.
↑TERPRI:PUSHJ 17,CARRET
PUSHJ 17,LINEFD
JRST CLREOL
; CARRET -- CR ;⊗ CARRET
; Call: PUSHJ 17,CARRET
; <return>
; Smashes 0.
↑CARRET:SKIPN WRAPPD ; recently wrap around from end of line?
JRST CARRE2 ; no
SKIPN HPOS ; redundant check for having just wrapped
SKIPL WRAPPD ; skip unless we had already seen a CR
SETZM WRAPPD ; forget that we have wrapped around
HRRZS WRAPPD ; we've seen at least a CR
CARRE2: MOVE 0,VPOS ; move to [0,current y]
JRST CSRPOS
; LINEFD -- LF, CLEOL, scroll if necessary ;⊗ LINEFD LINFD1 LINFD2
; Call: PUSHJ 17,CARRET
; <return>
; Smashes 0, 1, 2, 3, and 4.
↑LINEFD:SKIPE WRAPPD ;recently wrapped around from end of line?
JRST LINFD2 ;yes, ignore this LF
AOS 1,VPOS ;move to next line
CAMGE 1,VSIZE
JRST LINFD1
SKIPN ROLLP
JRST [ SETZM VPOS ↔ JRST LINFD1]
MOVE [SCREEN+NWRDLN,,SCREEN]
BLT SCREEN+SCRSIZ-NWRDLN-1
MOVE [<ASCII/ />+1]
MOVEM BOTLIN+1
MOVE [BOTLIN+1,,BOTLIN+2]
BLT BOTLIN+<NCHARS/5>
SETOM SAUPDP
MOVE VSIZE ↔ SOS ↔ MOVEM VPOS
SOSG SCRLCT
PUSHJ 17,SCNUPD ; update after a screenfull of scrolling
LINFD1: SETOM CRUPDP
POPJ 17,
LINFD2: SETZM WRAPPD ;forget that we had wrapped around
SKIPN HPOS ;redundant check to validate having just wrapped
POPJ 17,
JRST LINEFD ;oops, we forgot to clear WRAPPD somewhere!
; LINSRV -- Line starve ;⊗ LINSRV LINSR1
; Call: PUSHJ 17,LINSRV
; <return>
; Smashes 0.
↑LINSRV:SKIPN DMP
JRST LINSR1
DMCMD 32
LINSR1: SOSGE VPOS
SETZM VPOS
SETZM WRAPPD ;forget about any previous wrap around
SETOM CRUPDP
POPJ 17,
; CSRTAB -- Tab cursor ;⊗ CSRTAB CSRTA0
; Call: PUSHJ 17,CSRTAB
; <return>
; Smashes 0.
↑CSRTAB:SKIPE DMP
JRST CSRTA0
DMCMD 11 ; tab
CSRTA0: MOVE 0,HPOS
TRZ 0,7
ADDI 0,10
MOVEM 0,HPOS
PUSHJ 17,ADHPO2 ; check for wrap around
SETOM CRUPDP ; cursor updated
POPJ 17,
; CSRAOS -- Forespace cursor ;⊗ CSRAOS CSRAO0
; Call: PUSHJ 17,CSRAOS
; <return>
; Smashes 0.
↑CSRAOS:SKIPE DMP
JRST CSRAO0
DMCMD 34 ; forespace
CSRAO0: PUSHJ 17,ADHPOS ; increment HPOS and check for wrap around
SETOM CRUPDP ; cursor updated
POPJ 17,
; CSRSOS -- Backspace cursor ;⊗ CSRSOS CSRSO0
; Call: PUSHJ 17,CSRSOS
; <return>
; Smashes 0.
↑CSRSOS:SKIPE DMP
JRST CSRSO0
DMCMD 10 ; backspace
CSRSO0: SOSGE HPOS
SETZM HPOS
SETZM WRAPPD ; forget about any previous wrap around
SETOM CRUPDP ; cursor updated
POPJ 17,
; INSLIN -- Insert a blank line ;⊗ INSLIN INSLN0 INSL1A INSLN1 INSLN2
; Call: MOVE <number of lines to insert>
; PUSHJ 17,INSLIN
; <return>
; Smashes 0, 1, 2, and 3.
↑INSLIN:PUSH 17,0 ; save argument
SETZM WRAPPD ; forget about any previous wrap around
SKIPN DMP
JRST INSLN0
DMCMD 20 ; enter i/d mode on DM
INSLN0: SKIPN DMP
JRST INSL1A
DMCMD 12 ; insert a line on DM
INSL1A: MOVE 3,VPOS
IMULI 3,NWRDLN
ADDI 3,SCREEN ; address of first word of cursor line
CAIN 3,SCREEN+<NLINES-1>*NWRDLN ; skip unless at bottom line
JRST INSLN2
MOVE 1,[SCREEN+<NLINES-2>*NWRDLN,,SCREEN+<NLINES-1>*NWRDLN]
INSLN1: MOVE 2,1
BLT 2,NWRDLN-1(1) ; move line down
ADJSP 1,-NWRDLN
CAIE 3,(1)
JRST INSLN1
INSLN2: MOVE 1,[<ASCII/ />+1]
MOVEM 1,2(3)
MOVEI 1,NWRDLN-3(3)
ADDI 3,3
HRLI 3,-1(3)
BLT 3,(1)
SOSLE (17)
JRST INSLN0
ADJSP 17,-1 ; flush argument
SETOM SAUPDP
SKIPN DMP
POPJ 17,
DMCMD 30 ; leave i/d mode on DM
POPJ 17,
; DELLIN -- Delete a blank line ;⊗ DELLIN DELLN0 DELL1A DELLN1
; Call: MOVE <number of lines to delete>
; PUSHJ 17,DELLIN
; <return>
; Smashes 0, 1, 2, and 3.
↑DELLIN:PUSH 17, ; save argument
SETZM WRAPPD ; forget about any previous wrap around
SKIPN DMP
JRST DELLN0
DMCMD 20 ; enter i/d mode on DM
DELLN0: SKIPN DMP
JRST DELL1A
DMCMD 32 ; delete a line on DM
DELL1A: MOVE 3,VPOS
IMULI 3,NWRDLN
ADDI 3,SCREEN ; address of first word of cursor line
CAIN 3,SCREEN+<NLINES-1>*NWRDLN ; skip unless at bottom line?
JRST DELLN1
MOVEI 1,(3)
ADDI 1,NWRDLN
HRLI 3,(1)
BLT 3,SCREEN+<NLINES-1>*NWRDLN-1; move the lines up
DELLN1: MOVE 1,[<ASCII/ />+1]
MOVEM 1,2(3)
MOVEI 1,NWRDLN-3(3)
ADDI 3,3
HRLI 3,-1(3)
BLT 3,(1)
SOSLE (17)
JRST DELLN0
ADJSP 17,-1 ; flush argument
SETOM SAUPDP
SKIPN DMP
POPJ 17,
DMCMD 30 ; leave i/d mode on DM
POPJ 17,
; INSCHR -- Insert a blank character ;⊗ INSCHR INSCH0 INSC1A INSCH2 INSCH1
; Call: MOVE <number of spaces to insert>
; PUSHJ 17,INSCHR
; <return>
; Smashes 0, 1, 2, 3, 4, 5, and 6.
↑INSCHR:PUSH 17, ; save count
SETZM WRAPPD ; forget about any previous wrap around
SKIPN DMP ; is this a DM?
JRST INSCH0
DMCMD 20 ; yes, enter i/d mode
INSCH0: SKIPN DMP ; on a DM?
JRST INSC1A
DMCMD 34 ; insert a character
INSC1A: MOVE 1,VPOS ; get vertical position
IMULI 1,NWRDLN ; now number of words
MOVE 4,1 ; copy it for hacking
ADDI 4,SCREEN+NWRDLN-3 ; address of last text word
MOVE 2,HPOS ; get horizontal position
CAIL 2,LINEL ; within valid range?
JRST [ ADJSP 17,-1 ; no
POPJ 17,]
IDIVI 2,5 ; make it words
ADDI 1,SCREEN+2(2) ; address of word with cursor
LDB 2,[010700,,(1)] ; first character in next word
LDB 5,[ 103400,,(1)
102500,,(1)
101600,,(1)
100700,,(1)
100000,,(1)](3)
DPB 5,[ 013400,,(1)
012500,,(1)
011600,,(1)
010700,,(1)
010000,,(1)](3)
MOVEI 5," " ; space in hole
DPB 5,[ 350700,,(1)
260700,,(1)
170700,,(1)
100700,,(1)
010700,,(1)](3)
JRST INSCH1 ; check for being done
; At each iteration Y has last character, X has next address
INSCH2: MOVE 3,2 ; copy the character
LDB 2,[010700,,(1)] ; first character in next word
DPB 3,[000700,,(1)] ; last character here
MOVE 3,(1) ; get word being hacked
ROT 3,-7 ; put characters in right place
IORI 3,1 ; make sure bit 1.1 is on
MOVEM 3,(1) ; save character in word
INSCH1: CAME 1,4 ; at last address?
AOJA 1,INSCH2
SETOM SCUPDP ; some update somewhere
MOVE 1,VPOS ; this line
SOSLE (17)
JRST INSCH0 ; loop for more characters
ADJSP 17,-1
SETOM SLUPDP(1) ; this line was hacked
SKIPN DMP ; on a DM?
POPJ 17,
DMCMD 30 ; leave i/d mode
POPJ 17,
; DELCHR -- Delete a character ;⊗ DELCHR DELCH0 DELC1A DELCH2 DELCH1
; Call: MOVE <number of characters to delete>
; PUSHJ 17,DELCHR
; <return>
; Smashes 0, 1, 2, 3, 4, 5, and 6.
↑DELCHR:PUSH 17, ; save argument
SETZM WRAPPD ; forget about any previous wrap around
SKIPN DMP ; is this a DM?
JRST DELCH0
DMCMD 20 ; yes, enter i/d mode
DELCH0: SKIPN DMP ; on a DM?
JRST DELC1A
DMCMD 10 ; delete a character
DELC1A: MOVE 1,VPOS ; get current vertical position
IMULI 1,NWRDLN ; number of words
MOVE 4,1 ; save it for later
ADDI 4,SCREEN+NWRDLN-3 ; address of last text word in line
MOVE 2,HPOS ; get horizontal position
CAIL 2,LINEL ; within valid range?
JRST [ ADJSP 17,-1 ; no
POPJ 17,]
IDIVI 2,5 ; number of words
ADDI 1,SCREEN+2(2) ; address of word with cursor
LDB 5,[ 013400,,(1)
012500,,(1)
011600,,(1)
010700,,(1)
010000,,(1)](3)
DPB 5,[ 103400,,(1)
102500,,(1)
101600,,(1)
100700,,(1)
100000,,(1)](3)
JRST DELCH1 ; check for being done
; Each time around the iteration A had address of next word
DELCH2: LDB 2,[350700,,(1)] ; last character in previous
DPB 2,[010700,,-1(1)] ; to previous
LDB 2,[013400,,(1)] ; get last characters in this word
DPB 2,[103400,,(1)] ; put back left justified
DELCH1: CAME 1,4 ; done?
AOJA 1,DELCH2
MOVEI 2," " ; get a space
DPB 2,[010700,,(1)] ; blank out last column
SETOM SCUPDP ; screen updated someplace
MOVE 1,VPOS ; get this line
SOSLE (17)
JRST DELCH0 ; hack another character
ADJSP 17,-1
SETOM SLUPDP(1) ; flag this line hacked
SKIPN DMP ; on a DM?
POPJ 17,
DMCMD 30 ; leave i/d mode
POPJ 17,
; SCNUPD -- Update screen ;⊗ SCNUPD CSRUPD CSRNOE SCUPD1 SCUP1A SCUPD2 CSRER0 CSRERS
; Call: PUSHJ 17,SCNUPD
; <return>
; Smashes 0, 1, 2, 3, and 4.
↑SCNUPD:MOVSI 1,-NLINES
SETZ 2,
SKIPE SLUPDP(1) ; does this line need hacking?
ADDI 2,1
AOBJN 1,.-2
SKIPN IIIP ; III always updates everything
CAIL 2,4 ; after four lines update entire screen
SETOM SAUPDP
MOVE VSIZE
MOVEM SCRLCT
AOSE SAUPDP ; update entire screen?
JRST SCUPD1
SETZM SCUPDP ; clear other update flags
SETZM SLUPDP
MOVE [SLUPDP,,SLUPDP+1]
BLT SLUPDP+NLINES-1
SKIPE DMP ; is this a DM?
JRST [ PUSHJ 17,DMOUT
JRST CSRUPD]
UPGIOT SDISP ; output new screen on DD and III
; Update cursor
CSRUPD: SKIPE DMP ; is this a DM?
JRST [ DMCMD 14 ; cursor ← [0,2]
MOVE HPOS
XORI 140
PUSHJ 17,DMCHAR
MOVE VPOS
ADDI 2
XORI 140
PUSHJ 17,DMCHAR
JRST DMOUT]
SKIPN DDP ; no cursor stuff yet for III's
POPJ 17,
MOVEI 0,2
MOVEM 0,SCC+2
MOVE 0,[SCC+2,,SCC+3]
BLT 0,SCC+2+NGW-1 ; initialize graphics words
SKIPL 1,OVPOS ; got an old position?
CAMN 1,VPOS ; yes, different from new position?
JRST CSRNOE ; no or no, don't need to erase cursor
PUSHJ 17,CSRERS ; erase cursor
CSRNOE: MOVE 1,HPOS ; horizontal character position
CAIL 1,LINEL ; within valid range?
JRST CSRER0 ; no, just erase old cursor if any
IMULI 1,6 ; horizontal bit position
ADDI 1,2 ; graphics mode hack
IDIVI 1,=32 ; 32 bits/graphics word, get start word
MOVNS 2
repeat 0,< ; old slow code, doesn't immediately allow cursor bigger than 4 bits
MOVSI 3,740000 ; 4-bit cursor
LSH 3,(2)
LDB 4,[010300,,3]
ROT 4,-3
TRZ 3,17
>;repeat 0
repeat 1,< ; new speedy, general code (any size cursor)
MOVSI 3,760000 ; make cursor 5 bits wide
MOVEI 4,0
LSHC 3,-4(2) ; shift low four bits into second word
LSH 3,4 ; realign high 32 bits in first word
>;repeat 1
IORI 3,2 ; make two DD graphics words
IORI 4,2
DMOVEM 3,SCC+2(1)
MOVSI 1,700000 ; start cursor line with tiny cursor
IORM 1,SCC+2 ; in left margin
MOVE 1,VPOS ; save vertical position
MOVEM 1,OVPOS
PUSHJ 17,GETCSY
DDUPG CDISP ; draw new cursor
POPJ 17,
SCUPD1: AOSE SCUPDP ; did any update happen?
JRST SCUPD2
MOVSI 1,-NLINES
SCUP1A: SKIPE SLUPDP(1) ; need to hack this line?
PUSHJ 17,UPDLIN
AOBJN 1,SCUP1A
JRST CSRUPD
SCUPD2: AOSE CRUPDP ; was cursor hacked?
POPJ 17,
JRST CSRUPD
;Erase old cursor, if any.
CSRER0: SKIPGE 1,OVPOS ; skip if any old cursor
POPJ 17, ; nothing to erase
CSRERS: PUSHJ 17,GETCSY ; get cursor vertical position
DDUPG CDISP ; erase old cursor
SETOM OVPOS ; no cursor now
POPJ 17,
; Save and restore whole screen ;⊗ SCSAV1 SCSAV2 SCSAV3 SCSA12 SCSA21 SCRES1 SCRES2
; Save a copy of the screen image in core
; Smashes 1 and 2.
↑SCSAV1:SKIPA 1,[SCREEN,,SCREE1] ;save screen in primary copy
↑SCSAV2:MOVE 1,[SCREEN,,SCREE2] ;save screen in secondary copy
SCSAV3: MOVEI 2,(1)
BLT 1,LSTATE-1(2) ;save a copy of text on screen
POPJ 17,
↑SCSA12:MOVE 1,[SCREE1,,SCREE2] ;save primary copy in secondary copy
JRST SCSAV3
↑SCSA21:MOVE 1,[SCREE2,,SCREE1] ;save secondary copy in primary copy
JRST SCSAV3
; Restore a copy of the screen image from saved copy in core
; Smashes 1.
↑SCRES1:SKIPA 1,[SCREE1,,SCREEN] ;restore primary copy
↑SCRES2:MOVE 1,[SCREE2,,SCREEN] ;restore secondary copy
BLT 1,SCREEN+LSTATE-1 ;restore a saved copy of screen text
SETOM SAUPDP ;force screen update
SETOM CRUPDP ;force cursor update
POPJ 17,
; GETCSY UPDLIN Redisplay subroutines ;⊗ GETCSY UPDLIN
; Set up display program vertical position
GETCSY: IMULI 1,=12
ADDI 1,=24+=10
DPB 1,[140400,,SCC+1]
LSH 1,-4
DPB 1,[240500,,SCC+1]
POPJ 17,
; Display a single line
UPDLIN: SKIPE DMP
POPJ 17,
SKIPE LDISP+2
UPGIOT [0 ↔ 0 ↔ 0 ↔ 0] ; wait for previous
SETZM SLUPDP(1)
HRRZ 2,1 ; line number
IMULI 2,NWRDLN ; word position
MOVSI 2,SCREEN+2(2) ; address of start of line
HRRI 2,LNP+2
BLT 2,LNP+NWRDLN-2
HRRZ 2,1 ; get line number again
IMULI 2,=12
ADDI 2,=24 ; starting raster number
DPB 2,[140400,,LNP] ; zap in low 4 bits of address
LSH 2,-4 ; throw low bits away
DPB 2,[240500,,LNP] ; high 5 bits of address
UPGIOT LDISP ; display the line
POPJ 17,
; DMCHAR DMOUT Datamedia output routines ;⊗ DMCHAR DMOUT
; Character output to DM
DMCHAR: SOSG DMCNT ; any room in buffer?
PUSHJ 17,DMOUT
IDPB DMPNT ; save character
POPJ 17,
; Buffer output to DM; called when DM buffer full or want to force buffer out
↑DMOUT: SKIPN DMPGM ; any program there?
POPJ 17,
HRRZ DMPNT ; get current value of pointer
SUBI DMPGM-1 ; compute number of words used
MOVEM DMDISP+1 ; set number of words to do
UPGIOT DMDISP ; output DM program
MOVS HPOS
HRR VPOS
ADDI 2-1 ; two lines for who line
CURSOR ; bop the cursor to last position
SETZM DMPGM
MOVE [DMPGM,,DMPGM+1]
BLT DMPGM+DMBUFL-1 ; clear the old program
MOVEI <5*DMBUFL>-4
MOVEM DMCNT ; initialize DM counter
MOVE [440700,,DMPGM]
MOVEM DMPNT ; initialize DM pointer
MOVEI 177 ; quote
IDPB DMPNT
MOVEI 14 ; cursor position
IDPB DMPNT
MOVE HPOS ; horizontal position
XORI 140
IDPB DMPNT
MOVE VPOS ; vertical position
ADDI 2 ; who line space
XORI 140
IDPB DMPNT
POPJ 17,
BEND DISPLY